package npr.gui;

import processing.core.*;

public class FloatField extends TextInputField{
    
    private int initFrameCount;
    private float value, maxValue, minValue, step;
    private int precision;
    private Button upButton, downButton;
    private boolean up= false, down= false;

    public FloatField(int xpos, int ypos, int width, float minValue, float maxValue, float initValue, float step, int precision, String label){
	this(xpos, ypos, width, 22, null, defaultFontSize, minValue, maxValue, initValue, step, precision, label);
    }

    public FloatField(int xpos, int ypos, int width, int height, PFont font, int fontSize, float minValue, float maxValue, float initValue, float step, int precision, String label){

	super(xpos, ypos, width, height, font, fontSize, toString(initValue, precision), label, "");
       	this.minValue= minValue;
	this.maxValue= maxValue;
	this.value= initValue;
	this.step= step;
	this.precision= precision;  
	upButton= new Button(xpos+width, ypos, height/2, height/2);
	downButton= new Button(xpos+width, ypos+height/2, height/2, height/2);
    }

    private boolean up(int x, int y){
	return(x>xpos+width && x<xpos+width+height/2 && y>ypos && y<ypos+height/2);
    }

    private boolean down(int x, int y){
	return(x>xpos+width && x<xpos+width+height/2 && y>ypos+height/2 && y<ypos+height);
    }

    public void draw(){

	if(display){
	    parent.hint(DISABLE_DEPTH_TEST);
	    upButton.draw();
	    downButton.draw();
	    
	    float size= (float)height/2.0f;
	    
	    parent.fill(fontColor+50);
	    parent.noStroke();
	    
	    // up and down arrows
	    float offset=(size-(size-4.0f)/2.0f)/2.0f;
	    // up triangle
	    parent.triangle(xpos+width+2, ypos+size-offset , xpos+width+size-2, ypos+size-offset, xpos+width+size/2, ypos+offset);
	    // down triangle
	    parent.triangle(xpos+width+2, ypos+size+offset, xpos+width+size-2, ypos+size+offset, xpos+width+size/2, ypos+height-offset); 
	    
	    if(up) {
		float newValue= value+step*(float)(parent.frameCount-initFrameCount);
		if(newValue<maxValue)
		    value= newValue;
		else value= maxValue;
		setValue(value);
	    }
	    if(down) {
		float newValue= value-step*(float)(parent.frameCount-initFrameCount);
		if(newValue>minValue)
		    value= newValue;
		else value= minValue;
		setValue(value);
	    }    
	    super.draw();
	    parent.hint(ENABLE_DEPTH_TEST);
	}
    }

    public void enable(){
	super.enable();
	upButton.enable();
	downButton.enable();
    }

    public void disable(){
	super.disable();
	upButton.disable();
	downButton.disable();
    }


     protected void mousePressed(int x, int y){
	super.mousePressed(x, y);
	initFrameCount= parent.frameCount;
	value= getValue();
	if(up(x, y)){
	    if(value+step<maxValue)
		value+= step;
	    else value= maxValue;
	    setValue(value);
	    up= true;
	} 
	else if(down(x, y)){
	    if(value-step>minValue)
		value-= step;
	    else value= minValue;
	    setValue(value);
	    down= true;
	}
    }


     protected void mouseReleased(int x, int y){
	 up= down= false;
     }

     protected void keyPressed(char keyChar, int keyCode){
	 value= getValue();
	 if ((keyChar=='0' || 
	      keyChar=='1' || 
	      keyChar=='2' || 
	      keyChar=='3' || 
	      keyChar=='4' ||
	      keyChar=='5' ||
	      keyChar=='6' || 
	      keyChar=='7' || 
	      keyChar=='8' || 
	      keyChar=='9' ||
	      keyChar=='.' ||
	      keyChar=='-' ||
	      keyChar==DELETE ||
	      keyChar==BACKSPACE ||
	      keyChar==CODED ||
	      keyChar==ENTER || 
	      keyChar==RETURN)){
	     super.keyPressed(keyChar, keyCode);
	 }
	 if(hasInput){
	     try{
		 float newValue= getValue();
		 if(newValue<minValue){
		     setValue(minValue);
		 }
		 if(newValue>maxValue){
		     setValue(maxValue);
		 }
	     }
	     catch (NumberFormatException e){
		 setValue(value);
	     }
	 }
    }

    public float getValue(){
	if(hasInput()){
	    return Float.parseFloat(super.getInput());
	}
	else return value;
    }

    public void setValue(float value){
	super.setInput(toString(value, precision));
    }

    public static String toString(float value, int precision){

	String tmpStr = Float.toString(value);
	int pos = tmpStr.indexOf(".");

	if(pos != -1 && precision==0){
	    tmpStr = tmpStr.substring(0, pos);
	}
	else if(pos != -1 && pos+precision+1 <= tmpStr.length()){
	    tmpStr = tmpStr.substring(0, pos+precision+1);
	}
	
	return tmpStr;
    }
}
